package com.xy.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xy.constants.ControlCharacter;
import com.xy.constants.RabbitConstant;
import com.xy.constants.RedisConstant;
import com.xy.entity.ExhibitionEntity;
import com.xy.entity.TimeStageEntity;
import com.xy.entity.ViewerEntity;
import com.xy.entity.ViewerSortEntity;
import com.xy.eum.DataEum;
import com.xy.request.DataRequest;
import com.xy.request.QueueFaceDTO;
import com.xy.request.TimeStageRequest;
import com.xy.request.ViewerRequest;
import com.xy.response.DataErrorResponse;
import com.xy.response.DataResponse;
import com.xy.response.DataSussesResponse;
import com.xy.service.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.CollectionUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.xy.eum.DataEum.EXHIBITION_INFORMATION_ERROR;

@Service
@AllArgsConstructor
@Slf4j
public class DataThirdServiceImpl implements DataThirdService {
	private final IExhibitionService exhibitionService;
	private final IViewerService viewerService;
	private final IViewerSortService viewerSortService;
	private final BladeRedis bladeRedis;
	private final ITimeStageService timeStageService;
	private final RabbitTemplate rabbitTemplate;
	@Override
	public DataResponse saveData(DataRequest dataRequest) {
		getExhibition(dataRequest.getExhibitionId());
		List<ViewerRequest> viewerList = dataRequest.getViewerList();
		if(Func.isEmpty(viewerList)){
			throw new ServiceException("用户数据为空");
		}
		geRepeatData(viewerList);
		List<DataErrorResponse> dataErrorResponseList = new ArrayList<>();
		List<DataSussesResponse> dataSussesResponseList = new ArrayList<>();
		List<ViewerEntity> saveViewerEntityList = new ArrayList<>();
		Map<String, List<TimeStageRequest>> timeMap = new HashMap<>();
		viewerList.forEach(o->{
			o.setViewerId(null);
			ViewerSortEntity viewerSort = getViewerSort(o.getViewerTypeName(), dataRequest.getExhibitionId());
			Boolean geRepeatDataViewer = geRepeatDataViewer(o, viewerSort.getId(), dataRequest.getExhibitionId(), dataErrorResponseList);
			if(!geRepeatDataViewer){
				return;
			}
			ViewerEntity viewerEntity = BeanUtil.copy(o, ViewerEntity.class);
			viewerEntity.setViewerTypeId(viewerSort.getId());
			viewerEntity.setViewerSortFaceStatus(viewerSort.getFaceStatus());
			viewerEntity.setExhibitionId(dataRequest.getExhibitionId());
			viewerEntity.setSourceFrom(dataRequest.getSourceFrom());
			saveViewerEntityList.add(viewerEntity);
			timeMap.put(viewerEntity.getThirdPartyUnique(),o.getTimeStageList());
		});
		List<TimeStageEntity> timeStageEntityList = new ArrayList<>();
		if(Func.isNotEmpty(saveViewerEntityList)){
			viewerService.saveBatch(saveViewerEntityList);
			saveViewerEntityList.forEach(o->{
				if(Func.isNotBlank(o.getHeadUrl())){
					if(ControlCharacter.FACE_STATUS.equals(o.getFaceStatus()) || o.getViewerSortFaceStatus() == 0){
						QueueFaceDTO queueFaceDTO = BeanUtil.newInstance(QueueFaceDTO.class);
						queueFaceDTO.setTicketId(o.getId().toString());
						queueFaceDTO.setGroupId(o.getExhibitionId().toString());
						queueFaceDTO.setPhotoUrl(o.getHeadUrl());
						queueFaceDTO.setTicketName(o.getName());
						//  消息队列腾讯
						rabbitTemplate.convertAndSend(RabbitConstant.TOPIC_TENCENT_ADD_FACE_EXCHANGE,RabbitConstant.TOPIC_TENCENT_ADD_FACE_ROUTING_KEY_ONE,JSONObject.toJSONString(queueFaceDTO));
					}
				}
				cashViewerEntity(o);
				saveTimeStageEntity(timeMap,o,timeStageEntityList);
				dataSussesResponse(dataSussesResponseList,o);

				cashViewerEntity(o);
				saveTimeStageEntity(timeMap,o,timeStageEntityList);
				dataSussesResponse(dataSussesResponseList,o);
			});
		}
		if(Func.isNotEmpty(timeStageEntityList)){
			timeStageService.saveBatch(timeStageEntityList);
		}
		return returnData(dataErrorResponseList,dataSussesResponseList);
	}
	@Override
	public DataResponse updateData(DataRequest dataRequest) {

		getExhibition(dataRequest.getExhibitionId());
		List<ViewerRequest> viewerList = dataRequest.getViewerList();
		if(Func.isEmpty(viewerList)){
			throw new ServiceException("用户数据为空");
		}
		Map<String, List<ViewerRequest>> stringListMap = viewerList.stream().collect(Collectors.groupingBy(ViewerRequest::getViewerId));
		if (stringListMap.size() != viewerList.size()) {
			throw new ServiceException(DataEum.DUPLICATE_TICKETID_IN_DATA.getInfo());
		}
		geRepeatData(viewerList);
		List<DataErrorResponse> dataErrorResponseList = new ArrayList<>();
		List<DataSussesResponse> dataSussesResponseList = new ArrayList<>();
		List<ViewerEntity> updateViewerEntityList = new ArrayList<>();
		Map<String, List<TimeStageRequest>> timeMap = new HashMap<>();
		viewerList.forEach(o->{
			ViewerSortEntity viewerSort = getViewerSort(o.getViewerTypeName(), dataRequest.getExhibitionId());
			Boolean geRepeatDataViewer = geRepeatDataViewer(o, viewerSort.getId(), dataRequest.getExhibitionId(), dataErrorResponseList);
			if(!geRepeatDataViewer){
				return;
			}
			ViewerEntity viewerEntity = BeanUtil.copy(o, ViewerEntity.class);
			viewerEntity.setId(Func.toLong(o.getViewerId()));
			viewerEntity.setViewerTypeId(viewerSort.getId());
			viewerEntity.setViewerSortFaceStatus(viewerSort.getFaceStatus());
			viewerEntity.setExhibitionId(dataRequest.getExhibitionId());
			viewerEntity.setSourceFrom(dataRequest.getSourceFrom());
			updateViewerEntityList.add(viewerEntity);
			timeMap.put(viewerEntity.getThirdPartyUnique(),o.getTimeStageList());
		});
		List<TimeStageEntity> timeStageEntityList = new ArrayList<>();
		if(Func.isNotEmpty(updateViewerEntityList)){
			viewerService.updateBatchById(updateViewerEntityList);
			updateViewerEntityList.forEach(o->{
				updateTimeStageEntity(timeMap,o,timeStageEntityList);
				dataSussesResponse(dataSussesResponseList,o);
				if(Func.isNotBlank(o.getHeadUrl())){
					if(ControlCharacter.FACE_STATUS.equals(o.getFaceStatus())){
						QueueFaceDTO queueFaceDTO = BeanUtil.newInstance(QueueFaceDTO.class);
						queueFaceDTO.setTicketId(o.getId().toString());
						queueFaceDTO.setGroupId(o.getExhibitionId().toString());
						queueFaceDTO.setPhotoUrl(o.getHeadUrl());
						queueFaceDTO.setTicketName(o.getName());
						//  消息队列腾讯
						rabbitTemplate.convertAndSend(RabbitConstant.TOPIC_TENCENT_DELETE_FACE_EXCHANGE,RabbitConstant.TOPIC_TENCENT_DELETE_FACE_ROUTING_KEY_ONE,JSONObject.toJSONString(queueFaceDTO));
					}
				}
			});
		}
		if(Func.isNotEmpty(timeStageEntityList)){
			timeStageService.saveBatch(timeStageEntityList);
		}
		return returnData(dataErrorResponseList,dataSussesResponseList);
	}

	public void dataSussesResponse(List<DataSussesResponse> dataSussesResponseList,ViewerEntity viewerEntity){
		DataSussesResponse dataSussesResponse = BeanUtil.newInstance(DataSussesResponse.class);
		dataSussesResponse.setThirdPartyUnique(viewerEntity.getThirdPartyUnique());
		dataSussesResponse.setViewerId(Func.toStr(viewerEntity.getId()));
		dataSussesResponseList.add(dataSussesResponse);
	}

	private DataResponse returnData(List<DataErrorResponse> dataErrorResponseList,List<DataSussesResponse> dataSussesResponseList) {
		DataResponse dataResponse = BeanUtil.newInstance(DataResponse.class);
		dataResponse.setErrorList(dataErrorResponseList);
		dataResponse.setSussesList(dataSussesResponseList);
		return dataResponse;
	}

	public void updateTimeStageEntity(Map<String, List<TimeStageRequest>> timeMap,ViewerEntity viewerEntity,List<TimeStageEntity>  timeStageEntityList){
		timeStageService.remove(Wrappers.<TimeStageEntity>query().lambda().select(TimeStageEntity::getId).eq(TimeStageEntity::getViewerId, viewerEntity.getId()));
		saveTimeStageEntity(timeMap,viewerEntity,timeStageEntityList);
	}

	public void saveTimeStageEntity(Map<String, List<TimeStageRequest>> timeMap,ViewerEntity viewerEntity,List<TimeStageEntity>  timeStageEntityList){
		List<TimeStageRequest> timeStageRequests = timeMap.get(viewerEntity.getThirdPartyUnique());
		timeStageRequests.forEach(s->{
			if(Func.isEmpty(s.getStartTime()) || Func.isNotEmpty(s.getEndTime())){
				return;
			}
			TimeStageEntity timeStageEntity = BeanUtil.copy(s,TimeStageEntity.class);
			timeStageEntity.setDataType(1);
			timeStageEntity.setViewerId(viewerEntity.getId());
			timeStageEntityList.add(timeStageEntity);
		});
	}
	/**
	 * 缓存票证信息
	 */
	public void cashViewerEntity(ViewerEntity o){
		//保存成功缓存二维码
		if (Func.isNotBlank(o.getTwoCode())) {
			bladeRedis.set(RedisConstant.CASH_CARD_NO.concat(Func.toStr(o.getExhibitionId())).concat(o.getTwoCode()),JSONObject.toJSONString(o));
		}
		//保存成功缓存IC
		if (Func.isNotBlank(o.getSwipeCard())) {
			bladeRedis.set(RedisConstant.CASH_SWIPE_CARD_NO.concat(Func.toStr(o.getExhibitionId())).concat(o.getSwipeCard()), JSONObject.toJSONString(o));
		}
	}
	private ViewerSortEntity getViewerSort(String viewerTypeName,Long  exhibitionId){
		String key = RedisConstant.TYPE_ID_EX_TYPE_NAME.concat(Func.toStr(exhibitionId)).concat(viewerTypeName);
		ViewerSortEntity viewerSort = bladeRedis.get(key);
		if(Func.isNotEmpty(viewerSort)){
			return  viewerSort;
		}
		viewerSort = BeanUtil.newInstance(ViewerSortEntity.class);
		viewerSort.setSortName(viewerTypeName);
		viewerSort.setExhibitionId(exhibitionId);
		viewerSort.setFaceStatus(1);
		viewerSortService.save(viewerSort);
		bladeRedis.setEx(key,viewerSort, Duration.ofDays(10));

		return viewerSort;
	}

	public void getExhibition(Long  exhibitionId){
		ExhibitionEntity exhibition = exhibitionService.getById(exhibitionId);
		if (Func.isEmpty(exhibition)  || ControlCharacter.QUERY_STAUTS != exhibition.getCloseStatus()) {
			throw new ServiceException(EXHIBITION_INFORMATION_ERROR.getInfo());
		}
	}
	public List<ExhibitionEntity> getExhibitionStart(){
		List<ExhibitionEntity> exhibition = exhibitionService.list(Wrappers.<ExhibitionEntity>query().lambda().eq(ExhibitionEntity::getCloseStatus,ControlCharacter.QUERY_STAUTS));
		return exhibition;
	}
	public void geRepeatData(List<ViewerRequest> viewerList){
		List<ViewerRequest> viewerRequests = viewerList.stream().filter(x -> Func.isNotEmpty(x.getTwoCode())).collect(Collectors.toList());
		Map<String, List<ViewerRequest>> twoCodeMap = viewerRequests.stream().collect(Collectors.groupingBy(ViewerRequest::getTwoCode));
		if (CollectionUtil.isNotEmpty(twoCodeMap) && twoCodeMap.size() != viewerRequests.size()) {
			throw new ServiceException(DataEum.DUPLICATE_QR_CODE_DATA_EXISTS_IN_THE_DATA.getInfo());
		}
		List<ViewerRequest> viewerRequestList = viewerList.stream().filter(x -> Func.isNotEmpty(x.getSwipeCard())).collect(Collectors.toList());
		Map<String, List<ViewerRequest>> swipeCardMap = viewerRequestList.stream().collect(Collectors.groupingBy(ViewerRequest::getSwipeCard));
		if (CollectionUtil.isNotEmpty(viewerRequestList) && swipeCardMap.size() != viewerRequestList.size()) {
			throw new ServiceException(DataEum.DUPLICATE_RFID_DATA_EXISTS_IN_THE_DATA.getInfo());
		}
//		Map<String, List<ViewerRequest>> IdCardTypeNameMap = viewerList.stream().filter(x -> StringUtil.isNotBlank(x.getIdCard())).collect(Collectors.groupingBy(o->o.getIdCard()+o.getViewerTypeName()));
//		if (CollectionUtil.isNotEmpty(IdCardTypeNameMap) && IdCardTypeNameMap.size() != viewerList.size()) {
//			throw new ServiceException(DataEum.DUPLICATE_DATA_BETWEEN_ID_NUMBER_AND_TICKET_TYPE_IN_THE_DATA.getInfo());
//		}
	}

	public Boolean geRepeatDataViewer(ViewerRequest viewer,Long viewerSortId,Long exhibitionId,List<DataErrorResponse> dataErrorResponseList) {
		if(Func.isEmpty(viewer.getTwoCode())  && Func.isEmpty(viewer.getSwipeCard())){
			return true;
		}
		if (Func.isNotEmpty(viewer.getTwoCode())) {
			ViewerEntity viewerEntity = JSONObject.parseObject(bladeRedis.get(RedisConstant.CASH_CARD_NO.concat(Func.toStr(exhibitionId)).concat(viewer.getTwoCode())) ,ViewerEntity.class);;
			if (Func.isEmpty(viewerEntity)) {
				viewerEntity = getTwoCodeViewer(viewerSortId,exhibitionId,viewer.getTwoCode());
				log.info("进入数据库查询、卡号：{}", viewer.getTwoCode());
			}
			Boolean dataViewer = geRepeatDataViewer(viewerEntity, viewer, dataErrorResponseList);
			if(dataViewer){
				return true;
			}
		}
		if (Func.isNotEmpty(viewer.getSwipeCard())) {
			ViewerEntity viewerEntity  = JSONObject.parseObject(bladeRedis.get(RedisConstant.CASH_SWIPE_CARD_NO.concat(Func.toStr(exhibitionId)).concat(viewer.getSwipeCard())),ViewerEntity.class);
			if (Func.isEmpty(viewerEntity)) {
				viewerEntity = getSwipeCardViewer(viewerSortId,exhibitionId,viewer.getTwoCode());
				log.info("进入数据库查询、IC卡：{}", viewer.getTwoCode());
			}
			Boolean dataViewer = geRepeatDataViewer(viewerEntity, viewer, dataErrorResponseList);
			if(dataViewer){
				return true;
			}
		}
		return false;
	}
	public ViewerEntity getTwoCodeViewer(Long viewerSortId,Long exhibitionId,String twoCode){
		return viewerService.getOne(Wrappers.<ViewerEntity>query().lambda().eq(ViewerEntity::getExhibitionId,exhibitionId)
			.eq(ViewerEntity::getViewerTypeId,viewerSortId).eq(ViewerEntity::getTwoCode,twoCode));
	}
	public ViewerEntity getSwipeCardViewer(Long viewerSortId,Long exhibitionId,String swipeCard){
		return viewerService.getOne(Wrappers.<ViewerEntity>query().lambda().eq(ViewerEntity::getExhibitionId,exhibitionId)
			.eq(ViewerEntity::getViewerTypeId,viewerSortId).eq(ViewerEntity::getSwipeCard,swipeCard));
	}
	public Boolean geRepeatDataViewer(ViewerEntity viewerEntity ,ViewerRequest viewer,List<DataErrorResponse> dataErrorResponseList){

		if (Func.isEmpty(viewerEntity) ||  Func.toStr(viewerEntity.getId()).equals(viewer.getViewerId())) {
			return true;
		}
		DataErrorResponse dataErrorResponse = BeanUtil.instantiateClass( DataErrorResponse.class);
		dataErrorResponse.setViewerId(Func.toStr(viewerEntity.getId()));
		dataErrorResponse.setThirdPartyUnique(viewerEntity.getThirdPartyUnique());
		dataErrorResponse.setMessage(DataEum.DATA_ALREADY_EXISTS.getInfo());
		dataErrorResponse.setCode(DataEum.DATA_ALREADY_EXISTS.getCode());
		dataErrorResponseList.add(dataErrorResponse);
		return false;
	}
}
